package com.cathyjava.easyflows.workflow;

import com.cathyjava.easyflows.WorkStatus;
import com.cathyjava.easyflows.work.Work;
import com.cathyjava.easyflows.work.WorkContext;
import com.cathyjava.easyflows.work.WorkReport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * @author chenjing
 * @date 2021/5/7
 */
public class SequentialFlow extends AbstractWorkFlow {
    private static final Logger LOGGER = LoggerFactory.getLogger(SequentialFlow.class.getName());
    private List<Work> workUnits = new ArrayList<Work>();

    private SequentialFlow(String name, List<Work> workUnits) {
        super(name);
        this.workUnits.addAll(workUnits);
    }

    @Override
    public WorkReport execute(WorkContext workContext) {
        WorkReport workReport = null;
        for (Work work : this.workUnits) {
            workReport = work.execute(workContext);
            //中间工作单元失败，停止执行
            if (workReport != null && workReport.getStatus() == WorkStatus.FAIL) {
                LOGGER.info("SequentialFlow work unit ''{}'' 执行失败，退出", work.getName());
                break;
            }
        }
        return workReport;
    }

    public static class Builder {


        private Builder() {
        }

        public static NameStep aNewSequentialFlow() {
            return new BuildSteps();
        }

        public interface ExecuteStep {
            ThenStep execute(Work work);

            ThenStep execute(List<Work> workUnits);
        }

        public interface ThenStep {
            ThenStep then(Work work);

            ThenStep then(List<Work> workUnits);

            SequentialFlow build();
        }

        public interface NameStep extends ExecuteStep {
            ExecuteStep named(String name);
        }

        private static class BuildSteps implements NameStep, ThenStep, ExecuteStep {
            private String name;
            private List<Work> works;

            @Override
            public ThenStep execute(Work work) {
                this.works.add(work);
                return this;
            }

            public BuildSteps() {
                this.name = UUID.randomUUID().toString();
                this.works = new ArrayList<>();
            }

            @Override
            public ThenStep execute(List<Work> workUnits) {
                this.works.addAll(workUnits);
                return this;
            }

            @Override
            public ExecuteStep named(String name) {
                this.name = name;
                return this;
            }

            @Override
            public ThenStep then(Work work) {
                this.works.add(work);
                return this;
            }

            @Override
            public ThenStep then(List<Work> workUnits) {
                this.works.addAll(workUnits);
                return this;
            }

            @Override
            public SequentialFlow build() {
                return new SequentialFlow(this.name, this.works);
            }
        }
    }
}
